﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace HW2and3
{
    partial class ViewGUI : Form, ViewInterface, Observer
    {
        private ControllerInterface controller;
        private ModelBase model;

        private PictureBox[] Squares;

        public ViewGUI()
        {
            this.InitializeComponent();
            this.CenterToScreen();
            this.Show();
            this.BringToFront();
        }

        public void Initialize(string title, ControllerInterface controller)
        {
            this.controller = controller;
            this.Text = title;
            this.cmbModel.SelectedIndex = 0;
        }

        public void SetModel(string title, ModelBase model)
        {
            if (this.model != null)
                model.RemoveObserver(this);

            this.model = model;
            this.Text = title;

            model.RegisterObserver(this);

            ///cleanup
            if (Squares != null)
            {
                for (int i = 0; i < Squares.Length; i++)
                {
                    if (Squares[i] != null)
                    {
                        flpBoard.Controls.Remove(Squares[i]);
                    }
                }

                for (int i = 0; i < Squares.Length; i++)
                {
                    if (Squares[i] != null)
                    {
                        //Squares[i].Dispose();
                        Squares[i] = null;
                    }
                }
                Squares = null;
                System.GC.Collect();
            }

            ///set the board up...
            bool black = false;
            Squares = new PictureBox[model.Size * model.Size];
            for (int i = 0; i < Squares.Length; i++)
            {
                Squares[i] = new PictureBox();
                if(black)
                {
                    Squares[i].BackColor = picBlackSquare.BackColor;
                }
                else
                {   
                    Squares[i].BackColor = picWhiteSquare.BackColor;
                }

                black = !black;
                if ((i + 1) % model.Size == 0 && model.Size % 2 == 0) black = !black;

                Squares[i].Width = flpBoard.Width / model.Size;
                Squares[i].Height = flpBoard.Width / model.Size;
                Squares[i].SizeMode = picBlackSquare.SizeMode;
                Squares[i].Margin = picBlackSquare.Margin;

                flpBoard.Controls.Add(Squares[i]);
            }

            ///startup position...
            trkX.Maximum = model.Size - 1;
            trkY.Maximum = model.Size - 1;
            trkX.Value = model.X;
            trkY.Value = model.Y;
        }

        public void Update(StateInterface state, string msg, string info)
        {
            for (int i = 0; i < state.Board.GetLength(0); i++)
                for (int j = 0; j < state.Board.GetLength(0); j++)
                {
                    if (state.LastX == i && state.LastY == j)
                    {
                        if (controller.IsRunning()) Squares[i * state.Board.GetLength(0) + j].Image = imlImages.Images[0];
                    }
                    else if (state.Board[i, j] != 0)
                    {
                        if (controller.IsRunning()) Squares[i * state.Board.GetLength(0) + j].Image = imlImages.Images[1];
                    }
                    else
                    {
                        if (controller.IsRunning()) Squares[i * state.Board.GetLength(0) + j].Image = null;
                    }
                }
        }

        private void ViewGUI_Load(object sender, EventArgs e)
        {
            //
        }

        private void ViewGUI_Resize(object sender, EventArgs e)
        {
            int min = this.Width - 194 < this.Height - 58 ? this.Width - 194 : this.Height - 58;
            flpBoard.Width = min;
            flpBoard.Height = min;

            foreach (PictureBox Square in Squares)
            {
                Square.Width = flpBoard.Width / model.Size - 6;
                Square.Height = flpBoard.Width / model.Size - 6;
            }
        }

        private void cmbModel_SelectedIndexChanged(object sender, EventArgs e)
        {
            ConfigureModel();
        }

        private void ConfigureModel()
        {
            Behaviors.Behavior behavior = Behaviors.Behavior.KTDFS;

            switch (cmbModel.SelectedIndex)
            {
                case 0:
                    behavior = Behaviors.Behavior.KTDFS;
                    break;
                case 1:
                    behavior = Behaviors.Behavior.KTLA;
                    break;
                case 2:
                    behavior = Behaviors.Behavior.NQBFS;
                    break;
                case 3:
                    behavior = Behaviors.Behavior.NQLA;
                    break;
            }

            controller.SetModel(behavior, 5000 / this.trkSpeed.Value, this.trkSize.Value, this.trkX.Value, this.trkY.Value);
        }

        private void trkSize_ValueChanged(object sender, EventArgs e)
        {
            ConfigureModel();
        }

        private void btnStartStop_Click(object sender, EventArgs e)
        {
            if (controller.IsRunning())
                controller.Stop();
            else
            {
                if (controller.IsStopped())
                    ConfigureModel();
                controller.Start();
            }
            
        }

        private void ViewGUI_FormClosing(object sender, FormClosingEventArgs e)
        {
            controller.Stop();
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            controller.Pause();
        }

        private void trkX_Scroll(object sender, EventArgs e)
        {
            ConfigureModel();
            lblX.Text = "X = " + trkX.Value;
        }

        private void trkY_Scroll(object sender, EventArgs e)
        {
            ConfigureModel();
            lblY.Text = "Y = " + trkY.Value;
        }

        private void trkSpeed_Scroll(object sender, EventArgs e)
        {
            controller.SetSleepInterval(5000 / this.trkSpeed.Value);
        }
    }
}